/**
 * (c) 2015-2020
 *
 * Author: zeyuphoenix
 *
 * License: www.blogjava.net/zeyuphoenix
 *
 * version: 1.0.0
 */

(function (root, factory) {

    // "user strict";

    if (typeof define === 'function' && define.amd) {
        define(['jquery', 'datatables'], factory);
    } else {
        root.DataTableData = factory($, jQuery.fn.dataTable);
    }
}(this, function ($, DataTable) {

    // "user strict";

    /*
     * sets the defaults and adds options to DataTables to style its
     * controls using Bootstrap.
     */
    $.extend(true, DataTable.defaults, {
        "dom": "<'dt-toolbar'<'col-xs-12 col-sm-6'><'col-sm-6 col-xs-6 hidden-xs'>>" +
        "t" +
        "<'dt-toolbar-footer'<'col-sm-6 col-xs-12 hidden-xs'i><'col-sm-6 col-xs-12'p>>",
        /**默认关闭检索*/
        "searching": false,
        /**默认开启排序*/
        "ordering": true,
        /**默认开启分页*/
        "paging": true,
        /**默认开进度展示*/
        "processing": true,
        /**默认远程获取数据*/
        "serverSide": false,
        /**Enable or disable the table information display*/
        "info": true,
        /**例子: [[1, 'asc']]*/
        "order": {},
        /**
         * 使用lengthMenu选项来初始化选项，此选项支持两种参数方式，一种是一维数组，一种是二维数组
         */
        "lengthMenu": [
            [10, 25, 50, 100],
            [10, 25, 50, 100]
        ],
        /**
         * 默认情况下DataTable的分页就是上一页、下一页和6个页数按钮，而DataTable提供了四个模式供用户选择，通过设置 pagingType选项来配置
         * simple - 只有上一页、下一页两个按钮
         * simple_numbers - 除了上一页、下一页两个按钮还有页数按钮，DataTable默认是这个
         * full - 有四个按钮首页、上一页、下一页、末页
         * full_numbers - 除首页、上一页、下一页、末页四个按钮还有页数按钮
         */
        "pagingType": "simple_numbers",
        language: {
            "processing": "处理中...",
            "lengthMenu": "_MENU_ 记录/页",
            "zeroRecords": "没有匹配的记录",
            "info": "显示第 _START_ 至 _END_ 项记录，共 _TOTAL_ 项",
            "infoEmpty": "显示第 0 至 0 项记录，共 0 项",
            "infoFiltered": "(由 _MAX_ 项记录过滤)",
            "infoPostFix": "",
            "search": "过滤:",
            "url": "",
            "decimal": ",",
            "thousands": ".",
            "paginate": {
                "first": "首页",
                "previous": "上页",
                "next": "下页",
                "last": "末页"
            }
        },
        renderer: 'bootstrap'
    });

    /**
     * Pipelining function for DataTables. To be used to the `ajax` option of DataTables
     * @param opts
     * @returns {Function}
     */
    $.fn.dataTable.pipeline = function (opts) {
        // Configuration options
        var conf = $.extend({
            pages: 5,     // number of pages to cache
            url: '',      // script url
            data: null,   // function or object with parameters to send to the server
            // matching how `ajax.data` works in DataTables
            method: 'POST' // Ajax HTTP method
        }, opts);

        // Private variables for storing the cache
        var cacheLower = -1;
        var cacheUpper = null;
        var cacheLastRequest = null;
        var cacheLastJson = null;

        return function (request, drawCallback, settings) {
            var ajax = false;
            var requestStart = request.start;
            var drawStart = request.start;
            var requestLength = request.length;
            var requestEnd = requestStart + requestLength;

            if (settings.clearCache) {
                // API requested that the cache be cleared
                ajax = true;
                settings.clearCache = false;
            }
            else if (cacheLower < 0 || requestStart < cacheLower || requestEnd > cacheUpper) {
                // outside cached data - need to make a request
                ajax = true;
            }
            else if (JSON.stringify(request.order) !== JSON.stringify(cacheLastRequest.order) ||
                JSON.stringify(request.columns) !== JSON.stringify(cacheLastRequest.columns) ||
                JSON.stringify(request.search) !== JSON.stringify(cacheLastRequest.search)
            ) {
                // properties changed (ordering, columns, searching)
                ajax = true;
            }

            // Store the request for checking next time around
            cacheLastRequest = $.extend(true, {}, request);

            if (ajax) {
                // Need data from the server
                if (requestStart < cacheLower) {
                    requestStart = requestStart - (requestLength * (conf.pages - 1));

                    if (requestStart < 0) {
                        requestStart = 0;
                    }
                }

                cacheLower = requestStart;
                cacheUpper = requestStart + (requestLength * conf.pages);

                request.start = requestStart;
                request.length = requestLength * conf.pages;

                // Provide the same `data` options as DataTables.
                if ($.isFunction(conf.data)) {
                    // As a function it is executed with the data object as an arg
                    // for manipulation. If an object is returned, it is used as the
                    // data object to submit
                    var d = conf.data(request);
                    if (d) {
                        $.extend(request, d);
                    }
                }
                else if ($.isPlainObject(conf.data)) {
                    // As an object, the data given extends the default
                    $.extend(request, conf.data);
                }

                settings.jqXHR = $.ajax({
                    "type": conf.method,
                    "url": conf.url,
                    "data": request,
                    "dataType": "json",
                    "cache": false,
                    "success": function (json) {

                        // 匹配后台page分页接口封装
                        if (json && json != null && !$.isEmptyObject(json)) {
                            if (!json['draw'] && !json['recordsTotal'] && !json['data'] && json['tableData']) {
                                json = json['tableData'];
                            }
                        }

                        cacheLastJson = $.extend(true, {}, json);

                        if (cacheLower != drawStart) {
                            json.data.splice(0, drawStart - cacheLower);
                        }
                        json.data.splice(requestLength, json.data.length);

                        drawCallback(json);
                    }
                });
            }
            else {
                json = $.extend(true, {}, cacheLastJson);
                json.draw = request.draw; // Update the echo for each response
                json.data.splice(0, requestStart - cacheLower);
                json.data.splice(requestLength, json.data.length);

                drawCallback(json);
            }
        }
    };

    /**
     * Register an API method that will empty the pipelined data, forcing an Ajax
     * fetch on the next draw (i.e. `table.clearPipeline().draw()`)
     */
    $.fn.dataTable.Api.register('clearPipeline()', function () {
        return this.iterator('table', function (settings) {
            settings.clearCache = true;
        });
    });


    /**
     * Register an API method that will empty the pipelined data, forcing an Ajax
     * fetch on the next draw (i.e. `table.clearPipeline().draw()`)
     */
    $.fn.dataTable.Api.register('resetParams()', function (params) {
        return this.iterator('table', function (settings) {
            // console.info(params);
            settings.ajax = params;
        });
    });

    // 提供项目的默认配置项,保持风格统一,覆盖DataTable的配置项
    var defaultOptions = {
        //dom 节点
        databind: null,
        //数据请求url地址
        dataurl: '',
        //数据请求参数
        params: {},
        //本地模式才生效
        datas: null,
        // 因为后台有些数据不分页,需要直接返回所有
        alls: false,
        /**
         * 表头和表格值的显示主要在这个属性:
         * [{
         *      //默认都是false，不开启可以不写开启覆盖
         *      searchable: false,
         *      orderable: false,
         *      visible: true,
         *      render: function ( data, type, row ) {
		 *            return '<a href="'+data+'">Download</a>';
		 *      },
		 *      class: "",
		 *      width: null, ////"20%" or 20px
		 *      //必须项，表头和对应json的数据
		 *      data: "",
		 *      title: ""
         *  }，
         *  {
         *  }
         * ]
         */
        columns: null,
        //目前考虑不配制这个属性,配置的话需要 "targets":0
        columnDefs: null,

        /**默认开启检索*/
        searching: true,
        /**默认开启排序*/
        ordering: true,
        /**默认开启分页*/
        paging: true,
        /**默认开进度展示*/
        processing: true,
        /**是否展示条数信息*/
        info: true,
        /**默认远程获取数据*/
        serverSide: true,
        /**表的高度 -- 200px*/
        scrollY: "",
        /**自定义页面样式：每页行、过滤、信息、分页是否存在，还可添加自己需要的*/
        /**是一个dom，需要注意格式*/
        dom: '',

        /**是否有索引*/
        hasIndex: false,
        /**是否支持行选择*/
        hasSelect: false,
        /**是否支持多行选择*/
        hasMultSelect: false,
        /**是否有选择框,有选择框必然有多行选择*/
        hasCheck: false,
        /**checkbox 绑定数据列，必须与columns的data对应*/
        checkBind: "",
        /**是否有下拉扩展*/
        hasDetails: false,
        /**
         * 下拉框的详细
         * 目前支持html和function
         *
         * 1.html格式:
         *  details: '<div>Drop click this</div>',
         * 2.table格式:
         * details: function (row, $div, datatable) {
         *   //传入的是子DataTable的配置项，目前使用本地模式，不分页、不过滤、无cache、无选择框
         *   //覆盖传入模式，可以写入和datatable相同的配置项覆盖
         *
         *      //默认子table配置项，需要修改则覆盖
         *      var suboptions = {
         *          serverSide: false,
         *          searching: false,
         *          paging: false,
         *          hasCache: false,
         *          hasSelect: true,
         *          hasIndex: true,
         *          info: false,
         *      };
         *      //必须项目
         *      //远程模式则按照DataTable配置
         *      suboptions.databind = $div.get(0);
         *      suboptions.datas = subTableData;
         *      suboptions.columns = [
         *           { data: 'name', title: 'SubName' },
         *           { data: 'position', title: 'SubPos' },
         *           { data: 'salary', title: 'SubSal'},
         *           { data: 'office', title: 'SubOff' }
         *      ];
         *      var subDatatable = new DataTableData(suboptions);
         *      return $div.html();
         * }
         */
        details: "",
        /**是否使用页面缓存*/
        hasCache: false,
        /**页面缓存大小*/
        cachePages: 5,

        /**toolbar相关，默认vis、add、edit、delete、refresh*/
        /**默认显示toolbar*/
        showToolbar: true,
        /**
         * 默认全开放 add edit delete refresh, 根据key操作属性进行关闭和配置
         * 默认属性:
         * icon : "fa fa-refresh"
         * text : "add"
         * show : true
         * action : function(){}
         * tooltip : "add"
         *T
         * 可以通过 getToolbar append 新的按钮,自己加action
         */
        toolbarStates: {
            "add": {
                icon: "fa fa-plus",
                text: "add",
                show: true,
                tooltip: "add",
                action: null
            },
            "edit": {
                icon: "fa fa-edit",
                text: "edit",
                show: true,
                tooltip: "edit",
                action: null
            },
            "delete": {
                icon: "fa fa-trash-o",
                text: "delete",
                show: true,
                tooltip: "delete",
                mult: true,
                action: null
            },
            "refresh": {
                icon: "fa fa-refresh",
                text: "",
                show: true,
                tooltip: "refresh",
                action: null
            }
        },
        // 自己加的toolbar的按钮选择状态
        /**
         * {key:btn,这里不能直接使用jquery的对象,因为可能未初始化,需要使用dom,
         *  state:0   (0:总可用,1:单选可用,2:单多项可用 )
         * }
         */
        toolbarButonsStates: [],

        /**配置toolbar上vis相关信息*/
        colVis: {
            exclude: [],
            buttonText: "<i class='fa fa-list-ul'></i>",
            restore: "Restore",
            showAll: "Show all",
            showNone: "Show none"
            /**
             label: function (index, title, th) {
                return (index + 1) + '. ' + title;
            }*/
        },

        /**刷新表格*/
        refresh: null,
        /**
         * 单击行
         * 双击会触发一到两次单击，事件最好只用一个
         *   click :function(datatable, event){
         *      console.info(datatable);
         *      console.info(event);
         *   }
         * */
        click: null,
        /**
         * 双击行
         * 双击会触发一到两次单击，事件最好只用一个
         *   dblclick :function(datatable, event){
         *      console.info(datatable);
         *      console.info(event);
         *   }
         */
        dblclick: null,
        /**
         * Called when the table has been initialised.
         *    initComplete: function(settings, json) {
         *          alert( 'DataTables has finished its initialisation.' );
         *    }
         **/
        initComplete: null,
        /**
         * This function is called on every 'draw' event, and allows you to
         * dynamically modify any aspect you want about the created DOM.
         *
         "     drawCallback": function( settings ) {
         *          alert( 'DataTables has redrawn the table' );
         *     }
         */
        drawCallback: null,


        //额外接口,必须 和表的option保持一致,不要随便覆盖
        //这个里面的属性会在最后进行覆盖，如果你定义了上面的项目，会进行覆盖
        config: {}
    };

    // 表对象,创建的唯一入口
    var DataTableData = function (options) {
        this.options = $.extend(true, {}, defaultOptions, options);
        this.__init();
        this.build();
        this.request();
    };

    //表的配置
    //表的对象方法
    DataTableData.prototype = {

        // 构造
        constructor: DataTableData,

        // 获取默认的常量

        // 初始化
        __init: function () {
            var self = this;
            // 取得默认配置
            // 表的配置
            this.options.tableConfig = DataTable.defaults;
            //console.info(this.options.tableConfig);

            /**远程获取数据*/
            this.options.tableConfig.serverSide = this.options.serverSide;
            /**进度展示*/
            this.options.tableConfig.processing = this.options.processing;
            if (this.options.serverSide) {
                //build ajax 远程模式
                this.options.tableConfig.ajax = this.buildAjax();
            } else {
                //本地模式
                this.options.tableConfig.data = this.options.datas;
                this.options.tableConfig.processing = false;
            }
            // 一次获取所有,之后前台分页
            if (this.options.alls) {
                this.options.serverSide = false;
                this.options.hasCache = false;
                this.options.tableConfig.serverSide = false;
                this.options.tableConfig.ajax = this.buildAjax();
            }

            //设置column
            this.parseColumns(this.options.columns, this.options.columnDefs);

            /**开启检索*/
            this.options.tableConfig.searching = this.options.searching;
            /**开启排序*/
            this.options.tableConfig.ordering = this.options.ordering;
            /**开启分页*/
            this.options.tableConfig.paging = this.options.paging;
            /**开启信息*/
            this.options.tableConfig.info = this.options.info;

            /**设置高度*/
            if (this.options.scrollY != null && this.options.scrollY != "") {
                this.options.tableConfig.scrollY = this.options.scrollY;
                this.options.tableConfig.scrollCollapse = true;
            }

            /**设置toolbar*/
            if (this.options.showToolbar) {

                var vis = this.options.colVis;
                if (vis && vis != null) {

                    // 无意义时不可勾选
                    var count = 0;
                    if (this.options.hasIndex) {
                        count++;
                    }
                    if (this.options.hasCheck) {
                        count++;
                    }
                    if (this.options.hasDetails) {
                        count++;
                    }
                    if (count > 0) {
                        var excludes = [];
                        for (var i = 0; i < count; i++) {
                            excludes.push(i);
                        }
                        vis.exclude = excludes;
                    }
                    this.options.tableConfig.colVis = vis;
                }
                // 这里将要改写dom,如果你自己定义了dom,toolbar必须自己定义了
                this.options.tableConfig.dom = "<'dt-toolbar'<'col-xs-12 col-sm-6'C<'dt_action'>>r<'col-sm-6 col-xs-6 hidden-xs'<'dt_refresh'>>" +
                    "t" +
                    "<'dt-toolbar-footer'<'col-sm-6 col-xs-12 hidden-xs'i><'col-sm-6 col-xs-12'p>>";
            }

            /**设置dom*/
            if (this.options.dom && this.options.dom != null && this.options.dom != '') {
                this.options.tableConfig.dom = this.options.dom;
            }

            //注册完成事件
            if (this.options.initComplete != null && $.isFunction(this.options.initComplete)) {
                this.options.tableConfig.initComplete = this.options.initComplete;
            }
            //注册回调事件
            this.options.tableConfig.drawCallback = function () {

                //获取api对象
                var table = this.api();
                //添加索引列
                if (self.options.hasIndex) {
                    table.column('.index-control').nodes().each(function (cell, i) {
                        if (self.options.paging) {
                            if (i >= 10) {
                                // 前端全分页问题
                                cell.innerHTML = i + 1;
                            } else {
                                cell.innerHTML = i + 1 + table.page() * table.page.len();
                            }
                        } else {
                            cell.innerHTML = i + 1;
                        }
                    });
                }
                //修改选择框
                if (self.options.hasCheck) {
                    var checked = this.find('thead th input:checkbox').prop('checked');
                    if (checked && (checked == true || checked == "true" || checked == "checked")) {
                        this.find('thead th input:checkbox').prop('checked', false);
                    }
                    self.setStateByClick(0);
                }

                //修改详细框样式
                if (self.options.hasDetails) {
                    this.find('.details-control').addClass('details-control-padding');
                }

                //执行用户自己的回调
                if (self.options.drawCallback != null && $.isFunction(self.options.drawCallback)) {
                    var drawCallback = self.options.drawCallback;
                    if (drawCallback) {
                        if (typeof drawCallback == 'function') {
                            drawCallback.call(this, table);
                        }
                    }
                }
                // 动态代码,加载tooltip
                if ($("[rel='tooltip']").length) {
                    $("[rel=tooltip]").tooltip();
                }
            };

            // 验证是否用户使用额外接口
            if (this.options.config && !$.isEmptyObject(this.options.config)) {
                this.options.tableConfig = $.extend(true, this.options.tableConfig, this.options.config);
            }
        },

        /**
         * 注册表格单击、双击、选择、多选的事件
         */
        registerEvent: function (datatable) {
            var self = this;
            /**单击行*/
            //click: null
            datatable.on('click', 'tbody tr', datatable, function (event) {
                //不可选、单选、多选
                var checkStyle = 0;
                //存在选择框，必为多选
                if (self.options.hasCheck) {
                    checkStyle = 2;
                } else {
                    if (self.options.hasSelect) {
                        if (self.options.hasMultSelect) {
                            checkStyle = 2;
                        } else {
                            checkStyle = 1;
                        }
                    }
                }

                //选择处理
                if (checkStyle == 1) {
                    if ($(this).hasClass('info')) {
                        $(this).removeClass('info');
                    }
                    else {
                        event.data.api().$('tr.info').removeClass('info');
                        $(this).addClass('info');
                    }
                } else if (checkStyle == 2) {
                    $(this).toggleClass('info');

                    //选择按钮状态
                    if (self.options.hasCheck) {
                        //选择或去掉选择框
                        if ($(this).hasClass('info')) {
                            $(this).find('input:checkbox').prop('checked', "checked");
                        } else {
                            $(this).find('input:checkbox').prop('checked', false);
                        }
                        //根据选择状态决定全选按钮是否保留
                        var selLen = $(this).closest('table').find('tbody tr.info').length;
                        var tolLen = $(this).closest('table').find('tbody tr').length;
                        if (tolLen == selLen) {
                            $(this).closest('table').find('th input:checkbox').prop('checked', "checked");
                        } else {
                            $(this).closest('table').find('th input:checkbox').prop('checked', false);
                        }
                    }
                }

                //执行用户自己的单击
                var click = self.options.click;
                if (click) {
                    if (typeof click == 'function') {
                        // 防止checkbox多次触发
                        if ($(event.target).is('tr') || $(event.target).is('td'))
                            click.call(this, event.data, event);
                    }
                }
                // 更新按钮状态
                self.setStateByClick(self.getSelectedLength());
            });

            /**checkbox触发*/
            if (this.options.hasCheck) {
                datatable.on('click', 'tbody tr input:checkbox', datatable, function () {
                    $(this).closest('tr').trigger('click');
                });
            }

            /**双击行*/
            //dblclick: null
            datatable.on('dblclick', 'tbody tr', datatable, function (event) {
                //执行用户自己的双击
                var dblclick = self.options.dblclick;
                if (dblclick) {
                    if (typeof dblclick == 'function') {
                        dblclick.call(this, event.data, event);
                    }
                }
            });
            /**选择框*/
            if (this.options.hasCheck) {
                datatable.on('click', 'thead th input:checkbox', datatable, function () {
                    var all = this;
                    $(this).closest('table').find("input[name='checkList']").each(function () {
                        //this.checked = all.checked;
                        if (all.checked) {
                            $(this).closest('tr').addClass('info');
                            $(this).closest('tr').find('input:checkbox').prop('checked', "checked");
                        } else {
                            $(this).closest('tr').removeClass('info');
                            $(this).closest('tr').find('input:checkbox').prop('checked', false);
                        }
                    });
                    // 更新按钮状态
                    self.setStateByClick(self.getSelectedLength());
                });
            }

            /**扩展框*/
            // Add event listener for opening and closing details
            if (this.options.hasDetails) {
                datatable.on('click', 'td.details-control', datatable, function (event) {
                    var tr = $(this).closest('tr');
                    var row = event.data.api().row(tr);

                    //判断是否已打开
                    if (row.child.isShown()) {
                        // This row is already open - close it
                        row.child.hide();
                        tr.removeClass('shown');
                    }
                    else {
                        // Open this row
                        row.child(self.tableDetails(row, event.data)).show();
                        tr.addClass('shown');
                    }

                });
            }

        },

        /**
         * 生成表格的下拉项
         * @param row 选择行
         * @param datatable 选择表格
         * @returns {*} html
         */
        tableDetails: function (row, datatable) {
            //div获得
            var $div = $("<div class='sub_details' id='sub_" + row.index() + "_" + datatable.attr('id') + "'></div>");
            var details = this.options.details;
            if (details != null && details != "") {

                if (typeof details == 'function') {
                    details.call(this, row.data(), $div, datatable);
                    return $div;
                }

                return $div.html(this.options.details).html();
            }
        },
        /**
         * 添加索引列
         */
        addIndex: function (tableColumns) {
            if (this.options.hasIndex) {
                var column = {
                    class: 'index-control',
                    orderable: false,
                    searchable: false,
                    visible: true,
                    width: "20px",
                    data: null,
                    defaultContent: '',
                    title: ''
                };
                tableColumns.push(column);
            }
        },
        /**
         * 添加选择框
         */
        addCheckbox: function (tableColumns) {
            if (this.options.hasCheck) {
                var self = this;
                var column = {
                    class: 'check-control',
                    orderable: false,
                    searchable: false,
                    visible: true,
                    width: "16px",
                    data: null,
                    defaultContent: '',
                    // title: "<input type='checkbox' name='allCheck'>",
                    title: '<div class="checkbox" style="margin-bottom: 0;margin-top: 0;"><label><input type="checkbox" class="checkbox" name="allCheck"><span style="margin-right: 0;"></span></label></div>',
                    render: function (data, type, row) {
                        if (row != null && row != undefined) {
                            var bind = self.options.checkBind;
                            if (bind != null && bind != "" && row[bind] != null) {
                                //return "<input type='checkbox' name='checkList' value='" + row[bind] + "'>";
                                return '<div class="checkbox" style="margin-bottom: 0;margin-top: 0;"><label><input type="checkbox" class="checkbox" name="checkList" value="' + row[bind] + '"><span style="margin-right: 0;"></span></label></div>';
                            }
                        }
                        //return "<input type='checkbox' name='checkList'>";
                        return '<div class="checkbox" style="margin-bottom: 0;margin-top: 0;"><label><input type="checkbox" class="checkbox" name="checkList"><span style="margin-right: 0;"></span></label></div>';
                    }
                };
                tableColumns.push(column);
            }

        },
        /**
         * 添加展开框
         */
        addDetails: function (tableColumns) {
            if (this.options.hasDetails) {
                var column = {
                    class: 'details-control',
                    orderable: false,
                    searchable: false,
                    visible: true,
                    width: "18px",
                    data: null,
                    defaultContent: '',
                    title: ''
                };
                tableColumns.push(column);
            }
        },

        /**
         * build ajax request
         */
        buildAjax: function (params) {
            var self = this;
            var ajax = {};
            /**
             * 最终DataTable格式:
             *   ajax: {
             *       url: "data.json",
             *       type: "POST",
             *       data: function (d) {
             *             d.extra_search = $('#extra').val()
             *       }
             *   }
             *
             * 加入缓存的格式：
             *   ajax: $.fn.dataTable.pipeline( {
             *        url: 'data.json',
             *        method: "POST",
             *        data: function (d) {
             *             d.extra_search = self.options.params;
             *        }
             *        pages: 5 // number of pages to cache
             *   })
             */
            if (params == null || params == undefined || $.isEmptyObject(params)) {
                params = self.options.params;
            }
            if (this.options.hasCache) {
                //cache ajax
                ajax = $.fn.dataTable.pipeline({
                    url: self.options.dataurl,
                    method: "POST",
                    dataType: "json",
                    data: function (d) {
                        d.extra_search = JSON.stringify(params);

                        // 记录日志时请求中有很多垃圾属性,删除
                        delete d.columns;
                        delete d.order;
                        delete d.search;
                    },
                    pages: self.options.cachePages // number of pages to cache
                });
            } else {
                //simple ajax
                ajax = {
                    url: self.options.dataurl,
                    type: "POST",
                    dataFilter: function (data) {
                        // 匹配后台page分页接口封装
                        if (data != null) {
                            var json = jQuery.parseJSON(data);
                            if (!json['draw'] && !json['recordsTotal'] && !json['data'] && json['tableData']) {
                                return JSON.stringify(json['tableData']); // return JSON string
                            }
                        }
                        return data;
                    },
                    data: function (d) {
                        d.extra_search = JSON.stringify(params);

                        // 记录日志时请求中有很多垃圾属性,删除
                        delete d.columns;
                        delete d.order;
                        delete d.search;
                    }
                };
            }
            return ajax;
        },

        /**
         * 转换本地表头为DataTable格式
         * @param columns
         * 表头和表格值的显示主要在这个属性:
         * [{
         *      //默认都是false，不开启可以不写开启覆盖
         *      searchable: false,
         *      orderable: false,
         *      visible: false,
         *      render: function ( data, type, row ) {
		 *            return '<a href="'+data+'">Download</a>';
		 *      },
		 *      class: "",
		 *      width: null, ////"20%" or 20px
		 *      //必须项，表头和对应json的数据
		 *      data: "",
		 *      title: ""
         *  }，
         *  {
         *  }
         * ]
         *  @param columnDefs: null,暂时不利用，传值的话按照标准DataTable格式覆盖
         */
        parseColumns: function (columns, columnDefs) {
            var tableColumns = [];

            var defaultColumn = {
                searchable: false,
                orderable: false,
                visible: true,
                class: "",
                width: null,
                data: "",
                title: "",
                render: null,
                defaultContent: ''
            };

            //增加索引列
            this.addIndex(tableColumns);
            //增加选择框
            this.addCheckbox(tableColumns);
            //增加下拉详细框
            this.addDetails(tableColumns);

            if (columns != null && $.isArray(columns)) {
                $.each(columns, function (index, column) {
                    if (column.data == null || column.data == "") {
                        // 可以不设置,自定义下拉框时候
                        console.log('column data must be set!');
                    }
                    var col = $.extend(true, {}, defaultColumn, column);
                    tableColumns.push(col);
                });
            }

            //设置DataTable columns属性
            this.options.tableConfig.columns = tableColumns;

            //指定属性和列号，类似： [{ "cellType": "th", targets:0 }]
            this.options.tableConfig.columnDefs = columnDefs;
        },

        /**
         * 发送请求，取得表的数据
         * @params options 重新发送请求传递的参数
         */
        request: function () {
        },

        /**
         * 格式化Ajax请求的数据
         * @param options 所有的配置和数据
         */
        parseData: function (options) {
        },

        /**
         * 初始化后的表格
         * 需要api使用 .api()方法
         * @return dataTable 初始化后的表格
         */
        getDataTable: function () {
            return this.options.table;
        },

        refresh: function (params) {
            if (this.options.hasCache) {
                //clearPipeline()
                this.options.table.api().clearPipeline();
            }
//            if (params != null && params != undefined && !$.isEmptyObject(params)) {
//            }
            var ajax = this.buildAjax(params);
            this.options.table.api().resetParams(ajax);

            this.options.table.api().ajax.reload();
        },

        /**
         * 选择的行数
         * @return DataTable 选择的行数
         */
        getSelectedLength: function () {
            return this.options.table.api().rows('.info').data().length;
        },

        /**
         * 选择的数组
         * 不要使用for in，需要使用for index（会有自身对象）
         * @return Array 选择的数组
         */
        getSelectedDatas: function () {
            return this.options.table.api().rows('.info').data();
        },

        /**
         * 获取原始数据
         */
        getTableData: function () {
            return this.options.table.api().data();
        },

        /**
         * 根据点击后选择事件决定按钮的状态
         */
        setStateByClick: function (selNums) {

            if (this.options.table) {
                // 其它按钮
                var dt_action = $(this.options.databind).find('.dt-toolbar .dt_action');
                // 共通button
                var self = this;
                var mult = this.options.toolbarStates.delete.mult;
                self.updateBtnState(selNums, dt_action.find('.dt-edit-btn').get(0), 1);
                self.updateBtnState(selNums, dt_action.find('.dt-delete-btn').get(0), mult ? 2 : 1);
                // 加载用户自己的按钮状态
                var tbbs = this.options.toolbarButonsStates;
                if (tbbs != null && $.isArray(tbbs) && tbbs.length > 0) {
                    $.each(tbbs, function (i, value) {
                        if (value) {
                            self.updateBtnState(selNums, value['key'], value['state']);
                        }
                    });
                }
            }
        },

        /**
         * 更新状态
         */
        updateBtnState: function (selNums, btn, state) {
            var $btn = $(btn);
            if (state == 1) {
                // 单选
                if (selNums != 1) {
                    $btn.addClass('disabled');
                } else {
                    $btn.removeClass('disabled');
                }
            } else if (state == 2) {
                // 多选
                if (selNums == 0) {
                    $btn.addClass('disabled');
                } else {
                    $btn.removeClass('disabled');
                }
            }
        },

        /**
         * 获取默认子DataTable的配置项
         * @returns 子DataTable的配置项
         */
        getSubDefaultOptions: function () {
            //传入的是子DataTable的配置项，目前使用本地模式，不分页、不过滤、无cache、无选择框
            return {
                //默认table配置项，需要修改则覆盖
                serverSide: false,
                searching: false,
                paging: false,
                info: false,
                hasCache: false,
                hasSelect: true,
                hasIndex: true,
                //必须项目
                //远程模式则按照DataTable配置
                datas: [], //[｛name:'John',position:'china'｝]
                columns: []
            };
        },

        /**
         * 构造表
         */
        build: function () {
            if (this.options.table && this.options.table.fnDestroy) {
                this.options.table.fnDestroy();
            }
            //创建表格HTML
            $(this.options.databind).html('<table style="clear:both;width:100%;" class="table table-striped table-bordered table-hover datatable"><thead></thead><tbody></tbody></table>');
            //使用自定义主题
            this.options.table = $(this.options.databind).find('.datatable').dataTable(this.options.tableConfig);

            // 添加自定义按钮
            var states = this.options.toolbarStates;
            if (states && states != null) {
                // vis rset
                var self = this;
                $(this.options.databind).find('.ColVis button')
                    .removeClass().addClass('btn btn-link')
                    .attr('rel', 'tooltip').attr('data-placement', 'bottom')
                    .attr('data-original-title', 'show/hide columns');

                // 刷新按钮
                if (states.refresh.show) {
                    var dt_refresh = $(this.options.databind).find('.dt-toolbar .dt_refresh');
                    dt_refresh.append("<a class='btn btn-link dt-refresh-btn' rel='tooltip' data-placement='bottom' data-original-title='" +
                        states.refresh.tooltip +
                        "'><i class='" +
                        states.refresh.icon +
                        "'></i>" +
                        states.refresh.text +
                        "</a>");
                    if (states.refresh.action && $.isFunction(states.refresh.action)) {
                        dt_refresh.find('.dt-refresh-btn').on('click', states.refresh.action);
                    } else {
                        dt_refresh.find('.dt-refresh-btn').on('click', function () {
                            self.refresh();
                        });
                    }
                }
                // 其它按钮
                var dt_action = $(this.options.databind).find('.dt-toolbar .dt_action');
                if (states.add.show) {
                    dt_action.append("<span class='margin-left-5'></span>");
                    dt_action.append("<a class='btn btn-primary dt-add-btn' rel='tooltip' data-placement='bottom' data-original-title='" +
                        states.add.tooltip +
                        "'><i class='" +
                        states.add.icon +
                        "'></i> " +
                        states.add.text +
                        "</a>");
                    if (states.add.action && $.isFunction(states.add.action)) {
                        dt_action.find('.dt-add-btn').on('click', states.add.action);
                    }
                }
                if (states.edit.show) {
                    dt_action.append("<span class='margin-left-5'></span>");
                    dt_action.append("<a class='btn btn-info dt-edit-btn' rel='tooltip' data-placement='bottom' data-original-title='" +
                        states.edit.tooltip +
                        "'><i class='" +
                        states.edit.icon +
                        "'></i> " +
                        states.edit.text +
                        "</a>");
                    if (states.edit.action && $.isFunction(states.edit.action)) {
                        dt_action.find('.dt-edit-btn').on('click', states.edit.action);
                    }
                }
                if (states.delete.show) {
                    dt_action.append("<span class='margin-left-5'></span>");
                    dt_action.append("<a class='btn btn-warning dt-delete-btn' rel='tooltip' data-placement='bottom' data-original-title='" +
                        states.delete.tooltip +
                        "'><i class='" +
                        states.delete.icon +
                        "'></i> " +
                        states.delete.text +
                        "</a>");
                    if (states.delete.action && $.isFunction(states.delete.action)) {
                        dt_action.find('.dt-delete-btn').on('click', states.delete.action);
                    }
                }
            }

            //注册事件
            this.registerEvent(this.options.table);
        }
    };

    return DataTableData;
}));
